package com.sinothk.gpserver.modules.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sinothk.gpserver.config.shiro.JwtUtil;
import com.sinothk.gpserver.config.shiro.ShiroRealm;
import com.sinothk.gpserver.data.CommonConstant;
import com.sinothk.gpserver.data.DataConstant;
import com.sinothk.gpserver.modules.comm.serialNumber.service.SerialNumberService;
import com.sinothk.gpserver.modules.system.entity.*;
import com.sinothk.gpserver.modules.system.mapper.LoginMapper;
import com.sinothk.gpserver.modules.system.mapper.UserMapper;
import com.sinothk.gpserver.modules.system.service.ILoginService;
import com.sinothk.gpserver.modules.system.service.IUserRoleService;
import com.sinothk.gpserver.util.AvatarUtil;
import com.sinothk.gpserver.util.DateUtils;
import com.sinothk.server.support.annotation.callback.BizException;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import java.util.*;

/**
 * 编写 Liang Y.T.
 * 时间 2021/10/20 23:37
 */
@Service
public class LoginServiceImpl extends ServiceImpl<LoginMapper, LoginEntity> implements ILoginService {
    @Autowired
    private SerialNumberService snService;
    @Resource
    private LoginMapper loginMapper;
    @Resource
    private UserMapper userMapper;
    @Autowired
    IUserRoleService userRoleService;

    @Override
    @Transactional(rollbackFor = BizException.class)
    public LoginDto register(RegisterUserVo sysRegisterUser) {
        if (StringUtils.isBlank(sysRegisterUser.getPhoneNum())) throw new BizException("手机号码不能为空");
        if (StringUtils.isBlank(sysRegisterUser.getUserName())) throw new BizException("用户名不能为空");
        if (StringUtils.isBlank(sysRegisterUser.getPassword())) throw new BizException("密码不能为空");

        QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(UserEntity::getPhoneNum, sysRegisterUser.getPhoneNum());
        List<UserEntity> users = userMapper.selectList(wrapper);
        if (users.size() > 0) throw new BizException("手机号码已存在");

        QueryWrapper<UserEntity> wrapperUserName = new QueryWrapper<>();
        wrapperUserName.lambda().eq(UserEntity::getUserName, sysRegisterUser.getUserName());
        List<UserEntity> usersByName = userMapper.selectList(wrapperUserName);
        if (usersByName.size() > 0) throw new BizException("用户名已被占用");

        UserEntity userEntity = new UserEntity();
        BeanUtils.copyProperties(sysRegisterUser, userEntity);
        userEntity.setAccount(snService.generateSerialNumberByModelCode("用户"));
        userEntity.setUserAvatar(AvatarUtil.getRandomAvatar());
        userEntity.setCreateTime(DateUtils.getLocalDateTime());
        userEntity.setCreateBy(sysRegisterUser.getUserName());
        userEntity.setRoomCards(0);
        userMapper.insert(userEntity);

        // 生成用户默认默认角色
        UserRoleEntity userRole = new UserRoleEntity();
        userRole.setUserAccount(userEntity.getAccount());
        userRole.setRoles(DataConstant.RoleSystem.MEMBER);
        userRole.setCreateTime(DateUtils.getLocalDateTime());
        userRole.setCreateBy(userEntity.getAccount());
        userRoleService.save(userRole);

        // 添加登录账号
        LoginEntity loginEntity = new LoginEntity();
        BeanUtils.copyProperties(userEntity, loginEntity);
        loginEntity.setLoginTime(new Date());
        String md5Password = DigestUtils.md5DigestAsHex(sysRegisterUser.getPassword().getBytes());
        loginEntity.setPassword(md5Password);
        loginMapper.insert(loginEntity);

        // 返回登录信息
        UserEntity userNew = userMapper.selectOne(wrapper);
        userNew.setRoles(DataConstant.RoleSystem.MEMBER);
        LoginDto loginDto = new LoginDto();
        loginDto.setUser(userNew);
        loginDto.setToken(getTokenVal(loginEntity));
        return loginDto;
    }

    @Override
    @Transactional(rollbackFor = BizException.class)
    public LoginDto login(LoginVo loginVo) {
        if (StringUtils.isBlank(loginVo.getPhoneNum())) throw new BizException("手机号码不能为空");
        if (StringUtils.isBlank(loginVo.getPassword())) throw new BizException("密码不能为空");
        // 查询
        QueryWrapper<LoginEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(LoginEntity::getPhoneNum, loginVo.getPhoneNum());
        List<LoginEntity> users = loginMapper.selectList(wrapper);
        if (users == null || users.size() == 0) throw new BizException("此手机号码未注册");
        if (users.size() > 1) throw new BizException("此手机号码存在多个账号");

        //比较
        LoginEntity loginDb = users.get(0);
        String md5InputPassword = DigestUtils.md5DigestAsHex(loginVo.getPassword().getBytes());
        if (!md5InputPassword.equals(loginDb.getPassword())) throw new BizException("密码不正确");

        UserEntity userEntity = userMapper.selectByAccount(loginDb.getAccount());
        UserRoleEntity userRole = userRoleService.getOne(new LambdaQueryWrapper<UserRoleEntity>().eq(UserRoleEntity::getUserAccount, userEntity.getAccount()));
        if (userRole != null && userRole.getRoles() != null) {
            userEntity.setRoles(userRole.getRoles());
        }
        // 更新登录时间
        loginDb.setLoginTime(new Date());
        loginMapper.updateById(loginDb);

        // 返回登录信息
        LoginDto loginDto = new LoginDto();
        loginDto.setUser(userEntity);
        loginDto.setToken(getTokenVal(loginDb));
        return loginDto;
    }
    private String getTokenVal(LoginEntity user) {
        String token = JwtUtil.sign(user.getAccount(), user.getPassword());
        ShiroRealm.cacheMap.put(CommonConstant.PREFIX_USER_TOKEN + token, token);
        return token;//JwtUtil.sign(user.getAccount(), user.getPassword()); //JWTUtil.sign(user.getAccount(), user.getId(), "user");//TokenUtil.createToken(claimsInfo2, TokenUtil.TIME_DAY_30);
    }
    @Override
    public LoginDto loginAuto() {
        LoginEntity user = (LoginEntity) SecurityUtils.getSubject().getPrincipal();
        if (StringUtils.isBlank(user.getAccount())) throw new BizException("用户ID不能为空");

        UserEntity userEntity = userMapper.selectByAccount(user.getAccount());
        if (userEntity == null) throw new BizException("用户未注册");

        // 查询
        QueryWrapper<LoginEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(LoginEntity::getAccount, userEntity.getAccount());
        List<LoginEntity> userLogins = loginMapper.selectList(wrapper);
        if (userLogins == null || userLogins.size() == 0) throw new BizException("此手机号码未注册");
        if (userLogins.size() > 1) throw new BizException("此手机号码存在多个账号");
        // 更新登录时间
        LoginEntity loginDb = userLogins.get(0);
        loginDb.setLoginTime(new Date());
        loginMapper.updateById(loginDb);

        UserRoleEntity userRole = userRoleService.getOne(new LambdaQueryWrapper<UserRoleEntity>().eq(UserRoleEntity::getUserAccount, userEntity.getAccount()));
        if (userRole != null && userRole.getRoles() != null) {
            userEntity.setRoles(userRole.getRoles());
        }

        // 返回登录信息
        LoginDto loginDto = new LoginDto();
        loginDto.setUser(userEntity);
        loginDto.setToken(getTokenVal(loginDb));
        return loginDto;
    }


    @Override
    public Set<String> queryUserRoles(String username) {
        // 查询用户拥有的角色集合
        List<String> roles = new ArrayList<>();//’sysUserRoleMapper.getRoleByUserName(username);
//        log.info("-------通过数据库读取用户拥有的角色Rules------username： " + username + ",Roles size: " + (roles == null ? 0 : roles.size()));
        return new HashSet<>(roles);
    }

    @Override
    public Set<String> queryUserAuths(String username) {
        return getUserPermissionSet(username);
    }

    /**
     * 查询用户拥有的权限集合
     *
     * @param username
     * @return
     */
    @Override
    public Set<String> getUserPermissionSet(String username) {
        Set<String> permissionSet = new HashSet<>();
//        List<SysPermission> permissionList = sysPermissionMapper.queryByUser(username);
//        for (SysPermission po : permissionList) {
////			// TODO URL规则有问题？
////			if (oConvertUtils.isNotEmpty(po.getUrl())) {
////				permissionSet.add(po.getUrl());
////			}
//            if (oConvertUtils.isNotEmpty(po.getPerms())) {
//                permissionSet.add(po.getPerms());
//            }
//        }
//        log.info("-------通过数据库读取用户拥有的权限Perms------username： "+ username+",Perms size: "+ (permissionSet==null?0:permissionSet.size()) );
        return permissionSet;
    }

    @Override
    public LoginEntity getUserByAccount(String account) {
        LambdaQueryWrapper<LoginEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(LoginEntity::getAccount, account);
        return loginMapper.selectOne(wrapper);
    }


}
